package com.youtills.resource;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * TODO - !!!doc me!!!
 *
 * @author ravi.chiluveru
 * @since 23.0 (8/15/14)
 */
public final class ResourceRelationship<L extends Resource, R extends Resource>{

    public enum SourceLocation {
        left,
        right
    }

//    private final Resource resource;
    private final L leftResource;
    private final R rightResource;
    private final Resource resource;
    private final Relationship<L, R> relationship;
    private final SourceLocation sourceLocation;

    private final List<ResourceRelationshipValue<L,R>> values;
    private boolean immutable;
    private boolean modified;

    public ResourceRelationship(SourceLocation sourceLocation, L leftResource, R rightResource, Relationship<L, R> relationship) {

        if(sourceLocation == SourceLocation.left) {
            resource = leftResource;
        } else if (sourceLocation == SourceLocation.right) {
            resource = rightResource;
        } else {
            // todo throw exception.
            resource = null; // for now -- just go with null.
        }

        this.leftResource = leftResource;
        this.rightResource = rightResource;
        this.relationship = relationship;
        this.sourceLocation = sourceLocation;
        this.values = new ArrayList<>();

        if(resource instanceof BaseResource) {
            ((BaseResource)resource).addResourceRelationship(this);
        }
    }

    public Resource getResource() {
        return resource;
    }

    public SourceLocation getSourceLocation() {
        return sourceLocation;
    }

    public String getName() {
        return relationship.getRelationshipName();
    }

    Relationship getRelationship() {
        return relationship;
    }

    public boolean addTargetResourceId(Long targetResourceType, Long targetResourceId, String orderValue) {

        if(isImmutable()){
            return false;
        }

        final ResourceRelationshipValue<L, R> value = new ResourceRelationshipValue<L, R>(this, targetResourceType, targetResourceId, orderValue);
        boolean allowDuplicate = relationship.getAllowDuplicate() == null || relationship.getAllowDuplicate();

        if(allowDuplicate || !values.contains(value) ) { //TODO - verify if only order changes.
            this.values.add(value);
            if (resource instanceof BaseResource) {
                ((BaseResource) resource).addModifiedRelationshipValue(this);
                ((BaseResource) resource).setDirty(true);
            }
            return (modified = true);
        }

        return false;
    }

    public Long[] getTargetResourceIds() {
        Long[] resourceIds = new Long[values.size()];
        for(int i = 0; i < values.size(); i ++){
            resourceIds[i] = values.get(i).getResourceId();
        }

        return resourceIds;
    }

    public List<ResourceRelationshipValue<L,R>> getValues() {
        return Collections.unmodifiableList(this.values);
    }

    public boolean isModified() {
        return this.modified;
    }

    public boolean isImmutable() {
        return immutable || resource.isImmutable();
    }
}